#include "sm_gpio.h"
#include "esp_log.h"


#define TAG	"sm gpio"

ESP_EVENT_DEFINE_BASE(SM_GPIO_EVENT_BASE);

inline esp_err_t sm_gpio_init(sm_gpio_obj obj)
{
	gpio_config_t config = {0};

	config.pin_bit_mask		= BIT(obj.pin_num);
	config.mode				= obj.mode;
	config.pull_up_en		= obj.pull_up_en;
	config.pull_down_en		= obj.pull_down_en;
	config.intr_type		= obj.intr_type;
	
	return gpio_config(&config);
}

inline esp_err_t sm_gpio_set_pp_output(gpio_num_t io_num)
{
	gpio_config_t config = {0};

	config.pin_bit_mask		= BIT(io_num);
	config.mode				= GPIO_MODE_OUTPUT;
	config.pull_up_en		= 0;
	config.pull_down_en		= 0;
	config.intr_type		= 0;
	

	return gpio_config(&config);
}


inline esp_err_t sm_gpio_set_input(gpio_num_t io_num,gpio_int_type_t intr)
{
	gpio_config_t config = {0};

	config.pin_bit_mask		= BIT(io_num);
	config.mode				= GPIO_MODE_INPUT;
	config.pull_up_en		= 0;
	config.pull_down_en		= 0;
	config.intr_type		= intr;
	

	return gpio_config(&config);
}

esp_err_t sm_gpio_set_level(sm_gpio_obj obj,uint32_t level)
{
	if(obj.mode == GPIO_MODE_DISABLE || obj.mode == GPIO_MODE_INPUT)
	{
		ESP_LOGE(TAG,"pin [%d] not output mode,set level error!!!",(uint8_t)obj.pin_num);
		return ESP_FAIL;
	}

	return gpio_set_level(obj.pin_num,level);
}


int sm_gpio_get_level(sm_gpio_obj obj)
{
	if(obj.mode == GPIO_MODE_DISABLE || obj.mode == GPIO_MODE_OUTPUT || \
		obj.mode == GPIO_MODE_OUTPUT_OD)
	{
		ESP_LOGE(TAG,"pin [%d] not input mode,get level error!!!",(uint8_t)obj.pin_num);
		return ESP_FAIL;
	}

	return gpio_get_level(obj.pin_num);
}

inline esp_err_t sm_gpio_trigger(sm_gpio_obj obj)
{
	return sm_gpio_set_level(obj,!sm_gpio_get_level(obj));
}

static inline void sm_gpio_isr_callback(void *arg)
{
	sm_gpio_obj *obj = (sm_gpio_obj*)arg;

	xEventGroupSetBits(obj->event_handle, GPIO_EVENT_TRIGGER_BIT);
}


esp_err_t sm_gpio_register_event(sm_gpio_obj *obj)
{
	if(obj->intr_type == GPIO_INTR_DISABLE)
	{
		ESP_LOGE(TAG,"pin [%d] interrput mode is [GPIO_INTR_DISABLE],set interrput error!!!",obj->pin_num);
		return ESP_FAIL;
	}

	//IO的中断设置
	ESP_ERROR_CHECK(gpio_set_intr_type(obj->pin_num,obj->intr_type));

	//安装中断服务
	ESP_ERROR_CHECK(gpio_install_isr_service(0));

	//钩起特定的回调函数
	ESP_ERROR_CHECK(gpio_isr_handler_add(obj->pin_num,sm_gpio_isr_callback,(void*)obj));

	//创建事件,获取句柄
	obj->event_handle = xEventGroupCreate();

	//设置当前事件状态为空闲
	xEventGroupSetBits(obj->event_handle, GPIO_EVENT_IDLE_BIT);

	return ESP_OK;
}


//获取事件位
inline EventBits_t sm_gpio_get_event_bits(sm_gpio_obj *obj)
{
	return xEventGroupGetBits(obj->event_handle);
}

//设置事件位
inline EventBits_t sm_gpio_set_event_bits(sm_gpio_obj *obj,const uint32_t state)
{
	return xEventGroupSetBits(obj->event_handle,state);
}

//阻塞等待事件位被标志
inline EventBits_t sm_gpio_wait_event_bits(sm_gpio_obj *obj,const uint32_t state)
{
	return xEventGroupWaitBits(obj->event_handle,state,true,false,portMAX_DELAY);
}

